package cn.com.infcn.monitor.web;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.com.infcn.monitor.web.Counter.RequestCounterComparator;

public class RequestCounterAggregation {
	private final Counter counter;
	private final List<RequestCounter> requests;
	private final RequestCounter globalRequest;
	private final int warningThreshold;
	private final int severeThreshold;
	private final boolean responseSizeDisplayed;
	private final boolean timesDisplayed;
	private final boolean cpuTimesDisplayed;
	private final RequestCounter warningRequest;
	private final RequestCounter severeRequest;

	public RequestCounterAggregation(Counter counter) {
		super();
		assert counter != null;
		this.counter = counter;
		if (counter.isErrorCounter()) {
			this.requests = counter.getOrderedByHitsRequests();
		} else {
			this.requests = counter.getOrderedRequests();
		}
		assert requests != null;

		final String counterName = counter.getName();
		this.globalRequest = new RequestCounter(counterName + " global", counterName);
		for (final RequestCounter request : requests) {
			globalRequest.addHits(request);
		}

		this.responseSizeDisplayed = globalRequest.getResponseSizeMean() >= 0;
		this.timesDisplayed = globalRequest.getMean() >= 0;
		this.cpuTimesDisplayed = globalRequest.getCpuTimeMean() >= 0;

		final int globalMean = globalRequest.getMean();
		final int globalStandardDeviation = globalRequest.getStandardDeviation();
		this.warningThreshold = globalMean + globalStandardDeviation;
		this.severeThreshold = globalMean + 2 * globalStandardDeviation;

		this.warningRequest = new RequestCounter(counterName + " warning", counterName);
		this.severeRequest = new RequestCounter(counterName + " severe", counterName);
		for (final RequestCounter request : requests) {
			final int mean = request.getMean();
			if (mean > severeThreshold) {
				severeRequest.addHits(request);
			} else if (mean > warningThreshold) {
				warningRequest.addHits(request);
			}
		}
	}

	public List<RequestCounter> getRequests() {
		return requests;
	}

	public RequestCounter getGlobalRequest() {
		return globalRequest;
	}

	public RequestCounter getWarningRequest() {
		return warningRequest;
	}

	public RequestCounter getSevereRequest() {
		return severeRequest;
	}

	int getWarningThreshold() {
		return warningThreshold;
	}

	int getSevereThreshold() {
		return severeThreshold;
	}

	boolean isResponseSizeDisplayed() {
		return responseSizeDisplayed;
	}

	boolean isTimesDisplayed() {
		return timesDisplayed;
	}

	boolean isCpuTimesDisplayed() {
		return cpuTimesDisplayed;
	}

	List<RequestCounter> getRequestsAggregatedOrFilteredByClassName(String requestId) {
		final List<RequestCounter> requestsAggregatedByClassName = getRequestsAggregatedByClassName();
		final List<RequestCounter> requestList;
		if (requestId == null) {
			requestList = requestsAggregatedByClassName;
		} else {
			requestList = new ArrayList<RequestCounter>();
			for (final RequestCounter requestAggregated : requestsAggregatedByClassName) {
				if (requestId.equals(requestAggregated.getId())) {
					final String className = requestAggregated.getName();
					requestList.addAll(getRequestsFilteredByClassName(className));
					break;
				}
			}
		}
		return Collections.unmodifiableList(requestList);
	}

	private List<RequestCounter> getRequestsAggregatedByClassName() {
//		assert counter.isBusinessFacadeCounter();
		final Map<String, RequestCounter> requestMap = new HashMap<String, RequestCounter>();
		final String counterName = counter.getName();
		for (final RequestCounter request : getRequests()) {
			final String className = getClassNameFromRequest(request);
			RequestCounter global = requestMap.get(className);
			if (global == null) {
				global = new RequestCounter(className, counterName);
				requestMap.put(className, global);
			}
			global.addHits(request);
		}
		// on trie par la somme des durées
		final List<RequestCounter> requestList = new ArrayList<RequestCounter>(requestMap.values());
		if (requestList.size() > 1) {
			Collections.sort(requestList, Collections.reverseOrder(new RequestCounterComparator()));
		}
		return requestList;
	}

	private List<RequestCounter> getRequestsFilteredByClassName(String className) {
//		assert counter.isBusinessFacadeCounter();
		assert className != null;
		final List<RequestCounter> requestList = new ArrayList<RequestCounter>();
		for (final RequestCounter request : getRequests()) {
			final String requestClassName = getClassNameFromRequest(request);
			if (className.equals(requestClassName)) {
				requestList.add(request);
			}
		}
		if (requestList.size() > 1) {
			Collections.sort(requestList, Collections.reverseOrder(new RequestCounterComparator()));
		}
		return requestList;
	}

	private static String getClassNameFromRequest(RequestCounter request) {
		final int lastIndexOf = request.getName().lastIndexOf('.');
		if (lastIndexOf != -1) {
			return request.getName().substring(0, lastIndexOf);
		}
		return request.getName();
	}
}
